/*:
 * @plugindesc (v1.15)自定义鼠标指针
 * @author 小c
 * @version 1.11
 * @date 11/30/2021
 *
 * @param Cursor List
 * @text 鼠标指针列表
 * @type struct<cursorData>[]
 * @default []
 *
 * @param Cursor Z Index
 * @text 指针Z轴序号
 * @type number
 * @default 100
 *
 * @param Cursor Interval
 * @text 鼠标指针更新时间
 * @type number
 * @min 1
 * @desc 鼠标指针每次刷新的时间差，单位：帧
 * @default 10
 *
 * @param Default Cursor
 * @text 默认鼠标指针
 * @desc 此处参数必须为鼠标指针列表中的指针状态名之一
 *
 * @param Scene Cursors
 * @text 场景-指针对应表
 * @type struct<sceneCursors>[]
 * @desc 指定场景的默认指针设置
 * @default []
 *
 * @param Battle Cursors
 * @text 战斗-指针对应表
 * @type struct<battleCursors>[]
 * @desc 指定战斗阶段的默认指针设置，未设置时为Scene_Battle的场景指针
 * @default []
 *
 * @param Has Message Pause Cursor
 * @text 是否使用信息等待指针
 * @type boolean
 * @on 使用
 * @off 不使用
 * @desc 如果不使用，【信息框等待指针】将被忽略，此时信息框触发等待将不变换指针
 * @default false
 *
 * @param Message Pause Cursor
 * @text 信息框等待指针
 * @desc 此处参数必须为鼠标指针列表中的指针状态名之一
 *
 * @param Battle Phase Test
 * @text 战斗phase测试开关
 * @type boolean
 * @desc 开发者在战斗中测试哪些流程phase未设置指针的开关，当设为true时，战斗中会在控制台显示没有设置指针的phase
 * @default false
 *
 * @param Target Cursor
 * @text 战斗选择目标鼠标指针
 * @desc 此处参数必须为鼠标指针列表中的指针状态名之一
 *
 * @param Mouse Wait Count
 * @text 鼠标最大静止帧数
 * @type number
 * @min 1
 * @default 600
 * @desc 当鼠标静止不动一段时间后鼠标消失，单位【帧】
 *
 * @param Custom Mouse Hidden Condition
 * @text 鼠标隐藏额外条件
 * @type note
 * @default "condition = false;"
 * @desc JS代码块，布尔变量condition表示是否隐藏
 * 
 * @param Auto Execute Move Event
 * @text 是否自动触发移动事件
 * @type boolean
 * @on 触发
 * @off 不触发
 * @desc 测试方法启动游戏不操作鼠标【移动和点击】，鼠标若在正中间并迅速消失则为false，否则为true。测试时取false。
 * @default false
 *
 * @help 
 * 自定义鼠标指针。
 * 使用方法：
 * 1. 将鼠标指针png文件放入工程文件夹中你需要的位置
 * 2. 配置鼠标指针列表
 * （1）首先定义一组鼠标指针的状态名
 * （2）文件URL指定精灵指针的png图片，可以是帧动画
 * 路径以工程根目录为当前目录，举例：img/system/cursors/a.png
 * 图片帧动画以横向排列
 * （3）图片帧数指定该帧动画图片的长度
 * （4）原点取值范围[0, 1]，指定鼠标精灵的原点anchor
 * 3. 默认指针参数填入一个指针状态名，默认鼠标即为该指针动画
 * 4. 场景Scene与指针的对应关系配置中，场景Scene类名不可以是父类名
 * （比如Scene_MenuBase和Scene_File）
 * 类名对应关系
 * Scene_Title 封面
 * Scene_Map 地图
 * Scene_Menu 主菜单
 * Scene_Item 物品
 * Scene_Equip 装备
 * Scene_Skill 技能
 * Scene_Status 人物状态
 * Scene_Options 选项
 * Scene_Gameover 游戏结束
 * Scene_Battle 战斗，此处是战斗默认值
 *
 * 战斗配置请设置【战斗-指针对应表】
 * 此对应表配置战斗流程和指针的对应关系
 * 战斗阶段phase 一般有以下取值
 * input：战斗操作
 * turn：回合执行中
 * action：动作执行中
 * turnEnd：回合结束
 * 如果使用了YEP战斗核心，则是以下取值：
 * input：战斗操作
 * phaseChange：技能阶段变更【技能执行中】
 * actionList：技能动作序列【技能执行中】
 * actionTargetList：技能目标序列【技能执行中】
 * 如果使用了YEP的ATB插件，则还有这个：
 * atb：ATB读条过程中且没有任何其他动作
 *
 * 当战斗流程没有配置，鼠标则是战斗默认值
 * 如果你不知道有哪些phase需要测试，请把【战斗phase测试开关】设置为true
 * 当开关为true时，战斗过程中按下F12，会在控制台中显示你没有配置的phase
 * 测试完成后，请将开关重置为false
 *
 * 关于【信息框等待指针】
 * 当事件中的【显示文字】执行暂停时，如果使用信息等待指针，指针将会变为
 * 指定的指针
 * 但执行事件操作【显示选项】【数值输入处理】【道具选择处理】时将不执行
 * 变换
 *
 * JS函数
 * 用代码修改鼠标指针的方法
 * CP.CustomMouseCursor.setMouseCursorType(typeName) typeName为一个指针状态名
 *
 * SceneManager.resetSceneMouseCursor() 重设鼠标指针为当前Scene的指针
 * BattleManager.executeMouseCursorChanges() 重置鼠标为当前战斗状态（phase）
 * 的指针
 * $gameMap.currentMouseCursor() 返回当前地图的正常鼠标指针状态名
 * 注意：这个函数取值可以动态改变！
 *
 * 关于【是否自动触发移动事件】
 * 该插件参数需要测试一次才可以确定，测试条件为自身为false
 * 测试方法：启动游戏，不要操作鼠标【包括移动和点击都不要做】，如果鼠标
 * 出现在中间且短时间后【大约是 鼠标最大静止帧数 的十分之一，如果 鼠标
 * 最大静止帧数 低于300帧，则为30帧】后直接消失，则该参数取值为false，若
 * 鼠标指针偏移但不在准确坐标上，亦为false，否则应为true
 *
 * 关于【鼠标隐藏额外条件】
 * 该插件参数为一个JS代码块，控制布尔变量condition的取值，结果为true则强
 * 制隐藏鼠标指针
 * 若鼠标隐藏因该参数而起，鼠标静止时的计时将停止，该计时用于鼠标不操作时
 * 的消失计时
 * 
 * 更新日志
 * v1.00
 * 插件完成
 *
 * v1.01
 * 修复战斗测试结束会死机的问题
 * 添加战斗phase的测试开关
 *
 * v1.02
 * 鼠标指针更新时间单位变更为帧
 * 增加鼠标原点参数配置
 *
 * v1.03
 * 将地图的指针刷新处理核心增加至本插件中
 *
 * v1.04
 * 大幅修改参数结构，引入精灵指针
 *
 * v1.05
 * 修复由单帧指针变成多帧指针时指针显示错误的问题
 *
 * v1.06
 * 删除参数指针，引入canvas指针
 * 场景变化时鼠标可正常显示
 * 二级URL参数已删除
 *
 * v1.07
 * 增加鼠标指针Z轴序列参数
 * 修复鼠标在改变时会闪烁的问题
 *
 * v1.08
 * 修复程序错误时指针无法移动的BUG
 *
 * v1.09
 * 在游戏启动之后，鼠标移动之前，可以通过点击鼠标将指针坐标指向正确的
 * 位置。
 * 解决鼠标指针消失后直接点击鼠标，指针不恢复显示的问题
 *
 * v1.10
 * 游戏开始时若玩家没有操作鼠标，鼠标指针会很快消失
 * 消失帧数为【鼠标最大静止帧数】的十分之一与30帧的较大者
 * 增加一个屏蔽首次mousemove事件的插件参数，请根据测试结果设置
 *
 * v1.11
 * 追加显示文字信息框等待时的鼠标指针变换
 *
 * v1.12
 * 追加鼠标指针的额外隐藏条件
 * 更新到该版本时请及时确认插件参数
 *
 * v1.13
 * 修复战斗事件执行速度变快的问题
 *
 * v1.14
 * 修复窗口模式被拉伸之后鼠标与实际坐标发生偏差的问题
 *
 * v1.15
 * 修正战斗中选择替换宠物时指针为战斗input指针
 * 此更新为针对CP_PetCore的补充
 */
/*~struct~sceneCursors:
 * @param sceneClass
 * @text Scene类名
 * @parent Object Selectors
 *
 * @param cursorName
 * @text 指针状态名
 * @parent Object Selectors
 */
/*~struct~battleCursors:
 * @param phase
 * @text 战斗阶段phase
 * @parent Object Selectors
 *
 * @param cursorName
 * @text 指针状态名
 * @parent Object Selectors
 */
/*~struct~cursorData:
 * @param name
 * @text 指针状态名
 * 
 * @param url
 * @text 文件URL
 *
 * @param frames
 * @text 图片帧数
 * @type Number
 * @default 1
 *
 * @param anchorX
 * @text 原点X
 * @type number
 * @decimals 2
 * @min 0
 * @max 1
 * @desc 图片原点的X比例
 * @default 0.50
 *
 * @param anchorY
 * @text 原点Y
 * @type number
 * @decimals 2
 * @min 0
 * @max 1
 * @desc 图片原点的Y比例
 * @default 0.50
 */

var Imported = Imported || {};
Imported.CP_CustomMouseCursor = true;

var CP = CP || {};
CP.CustomMouseCursor = CP.CustomMouseCursor || {};
CP.CustomMouseCursor.Params = PluginManager.parameters("CP_CustomMouseCursor");

CP.CustomMouseCursor.getUrlData = function(url){
	var data = url.split("/");
	var name = data.pop().split(".")[0];
	var folder = data.join("/") + "/";
	return [folder, name];
};

CP.CustomMouseCursor.CURSOR_LIST = JSON.parse(CP.CustomMouseCursor.Params["Cursor List"]).map(function(cursorStr){
	var cursor = JSON.parse(cursorStr);
	cursor.frames = Number(cursor.frames) || 0;
	cursor.anchorX = Number(cursor.anchorX) || 0;
	cursor.anchorY = Number(cursor.anchorY) || 0;

	var data = this.getUrlData(cursor.url);
	cursor.bitmap = ImageManager.loadBitmap(data[0], data[1]);

	return cursor;
}.bind(CP.CustomMouseCursor));

CP.CustomMouseCursor.CURSOR_Z_INDEX = Number(CP.CustomMouseCursor.Params["Cursor Z Index"]) || 100; 
CP.CustomMouseCursor.CURSOR_INTERVAL = Number(CP.CustomMouseCursor.Params["Cursor Interval"]) || 10;
CP.CustomMouseCursor.DEFAULT_CURSOR = CP.CustomMouseCursor.Params["Default Cursor"];
CP.CustomMouseCursor.HAS_MESSAGE_PAUSE_CURSOR = eval(CP.CustomMouseCursor.Params["Has Message Pause Cursor"]) || false;
CP.CustomMouseCursor.MESSAGE_PAUSE_CURSOR = CP.CustomMouseCursor.Params["Message Pause Cursor"];

CP.CustomMouseCursor.SCENE_CURSORS = JSON.parse(CP.CustomMouseCursor.Params["Scene Cursors"]).map(function(item){
	return JSON.parse(item);
});

CP.CustomMouseCursor.BATTLE_CURSORS = JSON.parse(CP.CustomMouseCursor.Params["Battle Cursors"]).map(function(item){
	return JSON.parse(item);
});

CP.CustomMouseCursor.BATTLE_PHASE_TEST = eval(CP.CustomMouseCursor.Params["Battle Phase Test"]) || false;
CP.CustomMouseCursor.TARGET_CURSOR = CP.CustomMouseCursor.Params["Target Cursor"];

CP.CustomMouseCursor.MOUSE_WAIT_COUNT = Number(CP.CustomMouseCursor.Params["Mouse Wait Count"]) || 1;
CP.CustomMouseCursor.AUTO_EXECUTE_MOVE_EVENT = eval(CP.CustomMouseCursor.Params["Auto Execute Move Event"]) || false;
CP.CustomMouseCursor.CUSTOM_MOUSE_HIDDEN_CONDITION = new Function("condition"
	, JSON.parse(CP.CustomMouseCursor.Params["Custom Mouse Hidden Condition"]).trim() 
	+ "\nreturn condition;");

CP.CustomMouseCursor.setMousePosition = function(x, y){
	this._mouseRealX = x;
	this._mouseRealY = y;
};

CP.CustomMouseCursor.resetMousePosition = function(){
	var x = Math.round(Graphics.boxWidth / 2);
	var y = Math.round(Graphics.boxHeight / 2);
	this.setMousePosition(x, y);
	this.initMouseWaitCount();
};

CP.CustomMouseCursor.mouseX = function(){
	return this._mouseRealX;
};

CP.CustomMouseCursor.mouseY = function(){
	return this._mouseRealY;
};

CP.CustomMouseCursor.hideMouse = function(){
	document.body.style.cursor = "none";
};

CP.CustomMouseCursor.setMouseCursorType = function(typeName){
	this._cursorType = typeName;
};

CP.CustomMouseCursor.cursorType = function(){
	return this._cursorType;
};

CP.CustomMouseCursor.getMouseCursorData = function(){
	for(var i = 0; i < this.CURSOR_LIST.length; i++){
		var cursor = this.CURSOR_LIST[i];
		if(cursor.name === this._cursorType)
			return cursor;
	}

	return null;
};

CP.CustomMouseCursor.getMouseCursorBitmap = function(){
	var data = this.getMouseCursorData();
	return data ? data.bitmap : null;
};

CP.CustomMouseCursor.getMouseCursorFrame = function(){
	var data = this.getMouseCursorData();
	return !!data ? data.frames : 1;
};

CP.CustomMouseCursor.getMouseCursorAnchor = function(){
	var object = {x: 0, y: 0};
	var data = this.getMouseCursorData();
	if(!!data){
		object.x = data.anchorX;
		object.y = data.anchorY;
	}

	return object;
};

CP.CustomMouseCursor.refreshBattlePhase = function(){
	this._battlePhase = BattleManager._phase;
};

CP.CustomMouseCursor.isBattlePhaseNeedRefresh = function(){
	return this._battlePhase !== BattleManager._phase;
};

CP.CustomMouseCursor.initMouseWaitCount = function(){
	this._mouseWaitCount = Math.max(30, Math.floor(this.MOUSE_WAIT_COUNT / 10));
};

CP.CustomMouseCursor.resetMouseWaitCount = function(){
	this._mouseWaitCount = this.MOUSE_WAIT_COUNT;
};

CP.CustomMouseCursor.updateMouseWaitCount = function(){
	this._mouseWaitCount--;
	if(this._mouseWaitCount < -1)
		this._mouseWaitCount = -1;
};

CP.CustomMouseCursor.isMouseStop = function(){
	if(this._mouseWaitCount === undefined)
		this.initMouseWaitCount();
	return this._mouseWaitCount < 0;
};

//-----------------
// ImageManager
//-----------------
ImageManager.reserveMouseCursor = function(url, hue, smooth, reservationId){
	var data = CP.CustomMouseCursor.getUrlData(url);
	return this.reserveBitmap(data[0], data[1], hue, smooth, reservationId);
};

ImageManager.reserveAllMouse = function(){
	for(var i = 0; i < CP.CustomMouseCursor.CURSOR_LIST.length; i++){
		var data = CP.CustomMouseCursor.CURSOR_LIST[i];
		if(!!data.url){
			this.reserveMouseCursor(data.url, 0);
		}
	}
};

//-----------------
// Canvas_Mouse
//-----------------
function Canvas_Mouse(){
	this.initialize.apply(this, arguments);
};

Canvas_Mouse.prototype.initialize = function(x, y, width, height, id, zIndex){
	this._frameCount = 0; //帧计时
	this._currentFrame = 0; //当前帧序号
	this._maxFrame = 1; //动画帧长度
	this._resizeRefresh = false; //拉屏时请求刷新的标识

	this.setupCanvas(width, height, id, zIndex);
	this.resetRect(x, y, width, height);
	Graphics._disableContextMenu(); //禁止右键菜单

	this.show();
	this.setAnchor(0, 0);
	this.setupMouseBitmap();
	this.resetMouseFrameData();
	this.move(0, 0);
};

Canvas_Mouse.prototype.setupCanvas = function(width, height, id, zIndex){
	this._canvas = document.createElement("canvas");
	this._canvas.id = id;
	this._canvas.width = width;
	this._canvas.height = height;
	this._canvas.style.position = 'absolute';
    this._canvas.style.margin = 'auto';
	this._canvas.style.zIndex = zIndex;

	document.body.appendChild(this._canvas);
};

Canvas_Mouse.prototype.setupMouseBitmap = function(){
	this.setBitmap(CP.CustomMouseCursor.getMouseCursorBitmap());
};

Canvas_Mouse.prototype.resetRect = function(x, y, width, height){
	x = x || 0;
	y = y || 0;
	width = width || 0;
	height = height || 0;
	if(!this._rect)
		this._rect = new Rectangle(x, y, width, height);
	else{
		this._rect.x = x;
		this._rect.y = y; 
		this._rect.width = width;
		this._rect.height = height;
	}

	this.onWindowResize();
};

Canvas_Mouse.prototype.width = function(){
	return this._canvas.width;
};

Canvas_Mouse.prototype.height = function(){
	return this._canvas.height;
};

Canvas_Mouse.prototype.show = function(){
	this._hidden = false;
};

Canvas_Mouse.prototype.hide = function(){
	this._hidden = true;
};

Canvas_Mouse.prototype.isHidden = function(){
	if(this.customHiddenCondition())
		return true;
	return this._hidden;
};

//自定义隐藏条件
Canvas_Mouse.prototype.customHiddenCondition = function(){
	try{
		return CP.CustomMouseCursor.CUSTOM_MOUSE_HIDDEN_CONDITION.call(this, false);
	}catch(err){
		console.error(err);
		return false;
	}
};

Canvas_Mouse.prototype.setBitmap = function(bitmap){
	this._bitmap = bitmap;
};

Canvas_Mouse.prototype.move = function(x, y){
	this._x = x.clamp(0, this.width());
	this._y = y.clamp(0, this.height());
};

Canvas_Mouse.prototype.x = function(){
	var offsetX = 0;
	if(!!this.frame)
		offsetX = this._frame.width * this._anchorX;

	return this._x - offsetX;
};

Canvas_Mouse.prototype.y = function(){
	var offsetY = 0;
	if(!!this.frame)
		offsetY = this._frame.height * this._anchorY;

	return this._y - offsetY;
};

Canvas_Mouse.prototype.setFrame = function(x, y, width, height){
	if(!this._frame)
		this._frame = new Rectangle(x, y, width, height);
	else{
		this._frame.x = x;
		this._frame.y = y;
		this._frame.width = width;
		this._frame.height = height;
	}
};

Canvas_Mouse.prototype.frame = function(){
	return this._frame;
};

Canvas_Mouse.prototype.setAnchor = function(x, y){
	this._anchorX = x;
	this._anchorY = y;
};

Canvas_Mouse.prototype.context = function(){
	return this._canvas.getContext("2d");
};

Canvas_Mouse.prototype.clearRect = function(x, y, width, height){
	this.context().clearRect(x, y, width, height);
};

Canvas_Mouse.prototype.clear = function(){
	this.clearRect(0, 0, this.width(), this.height());
};

//强制请求鼠标变化
Canvas_Mouse.prototype.resizeRefresh = function(){
	this._resizeRefresh = true;
};

Canvas_Mouse.prototype.onWindowResize = function() {
    var top = Graphics._canvas.offsetTop;
    var left = Graphics._canvas.offsetLeft;
    this._lastScale = Graphics._realScale;
    this._lastWindowWidth = document.body.clientWidth;
    this._lastWindowHeight = document.body.clientHeight;
    this._canvas.style.top = this._rect.y * this._lastScale + top + 'px';
    this._canvas.style.left = this._rect.x * this._lastScale + left + 'px';
    this._canvas.style.width = this._rect.width * this._lastScale + 'px';
    this._canvas.style.height = this._rect.height * this._lastScale + 'px';
    this._resizeRefresh = false;
};

Canvas_Mouse.prototype.isCanvasResizeNeeded = function(){
	return this._resizeRefresh || this._lastScale !== Graphics._realScale ||
    	this._lastWindowWidth !== document.body.clientWidth ||
   		this._lastWindowHeight !== document.body.clientHeight;
};

Canvas_Mouse.prototype.resetMouseFrameData = function(){
	this._frameCount = 0;
	this._currentFrame = 0;
	this._maxFrame = CP.CustomMouseCursor.getMouseCursorFrame();
	this.updateFrame();
};

Canvas_Mouse.prototype.refreshAnchor = function(){
	var anchor = CP.CustomMouseCursor.getMouseCursorAnchor();
	this.setAnchor(anchor.x, anchor.y);
};

Canvas_Mouse.prototype.isAnchorChanged = function(){
	var anchor = CP.CustomMouseCursor.getMouseCursorAnchor();
	return this._anchorX !== anchor.x || this._anchorY !== anchor.y;
};

Canvas_Mouse.prototype.update = function(){
	this.updateSize();
	this.updateBitmap();
	this.updateAnchor();
	this.updateFrameCount();
	this.updatePosition();
	this.updatePaint();
};

Canvas_Mouse.prototype.updateSize = function(){
	if(this.isCanvasResizeNeeded())
		this.onWindowResize();
};

Canvas_Mouse.prototype.updateBitmap = function(){
	if(this._bitmap !== CP.CustomMouseCursor.getMouseCursorBitmap()){
		this.setupMouseBitmap();
		this.resetMouseFrameData();
	}
};

Canvas_Mouse.prototype.updatePaint = function(){
	this.clear();
	if(!this.isHidden())
		this.drawBitmap();
};

Canvas_Mouse.prototype.drawBitmap = function(){
	var x = this.x();
	var y = this.y();
	var frame = this.frame();
	this.context().drawImage(this._bitmap._canvas, frame.x, frame.y, frame.width, frame.height, x, y, frame.width, frame.height);
};

Canvas_Mouse.prototype.updateFrameCount = function(){
	this._frameCount++;
	if(this._frameCount >= CP.CustomMouseCursor.CURSOR_INTERVAL)
		this.updateFrame();
};

Canvas_Mouse.prototype.updateFrame = function(){
	var width = Math.floor(this._bitmap.width / this._maxFrame);
	var height = this._bitmap.height;
	this.setFrame(width * this._currentFrame, 0, width, height);
	this._currentFrame = (this._currentFrame + 1) % this._maxFrame;
	this._frameCount = 0;
};

Canvas_Mouse.prototype.updateAnchor = function(){
	if(this.isAnchorChanged())
		this.refreshAnchor();
};

Canvas_Mouse.prototype.updatePosition = function(){
	var x = CP.CustomMouseCursor.mouseX();
	var y = CP.CustomMouseCursor.mouseY();
	this.move(x || 0, y || 0);
};

//-----------------
// Game_Map
//-----------------
Game_Map.prototype.currentMouseCursor = function(){
	return null;
};

CP.CustomMouseCursor.UPDATE_MAP = Game_Map.prototype.update;
Game_Map.prototype.update = function(sceneActive){
	CP.CustomMouseCursor.UPDATE_MAP.call(this, sceneActive);
	this.updateMapMouseCursor(sceneActive);
};

Game_Map.prototype.updateMapMouseCursor = function(sceneActive){
	if(sceneActive && !this.isEventRunning()){
		var cursor = this.currentMouseCursor();
		if(!!cursor)
			CP.CustomMouseCursor.setMouseCursorType(cursor);
		else
			SceneManager.resetSceneMouseCursor();
	}else if(this.isEventRunning())
		SceneManager.resetSceneMouseCursor();
};

//-----------------
// SceneManager
//-----------------
CP.CustomMouseCursor.INIT_SCENE_MANAGER = SceneManager.initialize;
SceneManager.initialize = function(){
	CP.CustomMouseCursor.INIT_SCENE_MANAGER.call(this);
	CP.CustomMouseCursor.resetMousePosition();
};

CP.CustomMouseCursor.GOTO_SCENE = SceneManager.goto;
SceneManager.goto = function(sceneClass){
	CP.CustomMouseCursor.GOTO_SCENE.call(this, sceneClass);
	if(!!sceneClass)
		this.changeSceneMouseCursor(sceneClass);
};

SceneManager.sceneCursor = function(sceneClass){
	var className = sceneClass.name;
	for(var i = 0; i < CP.CustomMouseCursor.SCENE_CURSORS.length; i++){
		var cursor = CP.CustomMouseCursor.SCENE_CURSORS[i];
		if(cursor.sceneClass == sceneClass.name)
			return cursor.cursorName;
	}

	return CP.CustomMouseCursor.DEFAULT_CURSOR;
};

SceneManager.changeSceneMouseCursor = function(sceneClass){
	var cursor = this.sceneCursor(sceneClass);
	CP.CustomMouseCursor.setMouseCursorType(cursor);
};

SceneManager.resetSceneMouseCursor = function(){
	this.changeSceneMouseCursor(this._scene.constructor);
};

CP.CustomMouseCursor.STOP_GAME_SCENE = SceneManager.stop;
SceneManager.stop = function(){
    CP.CustomMouseCursor.STOP_GAME_SCENE.call(this);
    this.requestUpdate(); //死机时需要继续启动循环
};

CP.CustomMouseCursor.REQUEST_SCENE_UPDATE = SceneManager.requestUpdate;
SceneManager.requestUpdate = function(){
	if(this._stopped)
		requestAnimationFrame(this.updateMouseCanvasWhenGameStop.bind(this)); //死机的时候修改为死机循环
	else
		CP.CustomMouseCursor.REQUEST_SCENE_UPDATE.call(this);
};

CP.CustomMouseCursor.UPDATE_ALL_SCENE = SceneManager.update;
SceneManager.update = function(){
	CP.CustomMouseCursor.UPDATE_ALL_SCENE.call(this);
	
	if(!Utils.isMobileDevice()){
		this.updateMouseCanvas();
		if(!!this._mouseCanvas && !this._mouseCanvas.customHiddenCondition())
			CP.CustomMouseCursor.updateMouseWaitCount();
	}
};

SceneManager.updateMouseCanvas = function(){
	if(!this._mouseCanvas)
		this._mouseCanvas = new Canvas_Mouse(0, 0, Graphics.boxWidth, Graphics.boxHeight, "MouseCanvas"
			, CP.CustomMouseCursor.CURSOR_Z_INDEX);
	this._mouseCanvas.update();
	if(CP.CustomMouseCursor.isMouseStop())
		this.hideMouse();
};

//死机时循环
SceneManager.updateMouseCanvasWhenGameStop = function(){
	if(!Utils.isMobileDevice()){
		this.updateMouseCanvas();
		CP.CustomMouseCursor.updateMouseWaitCount();
	}
	this.requestUpdate();
};

SceneManager.hideMouse = function(){
	if(!!this._mouseCanvas)
		this._mouseCanvas.hide();
	TouchInput.setMovedFlag();
};

SceneManager.showMouse = function(){
	if(!!this._mouseCanvas)
		this._mouseCanvas.show();
};

SceneManager.moveMouse = function(x, y){
	CP.CustomMouseCursor.setMousePosition(x, y);
};

//刷新鼠标尺寸范围，窗口变更执行
SceneManager.resizeMouseRefresh = function(){
	if(this._mouseCanvas)
		this._mouseCanvas.resizeRefresh();
};

//-----------------
// BattleManager
//-----------------
CP.CustomMouseCursor.BATTLE_INIT_MEMBERS = BattleManager.initMembers;
BattleManager.initMembers = function(){
	CP.CustomMouseCursor.BATTLE_INIT_MEMBERS.call(this);
	this._showBattleMouseCursor = false; //显示战斗场景默认图标
};

CP.CustomMouseCursor.UPDATE_BATTLE_EVENT = BattleManager.updateEvent;
BattleManager.updateEvent = function(){
	if(CP.CustomMouseCursor.UPDATE_BATTLE_EVENT.call(this)){
		this._showBattleMouseCursor = true;
		return true;
	}else
		return false;
};

CP.CustomMouseCursor.UPDATE_BATTLE = BattleManager.update;
BattleManager.update = function(){
	CP.CustomMouseCursor.UPDATE_BATTLE.call(this);
	if(this._showBattleMouseCursor)
		SceneManager.resetSceneMouseCursor();
	else
		this.updateMouseCursor();
	this._showBattleMouseCursor = false;
};

BattleManager.updateMouseCursor = function(){
	if(CP.CustomMouseCursor.isBattlePhaseNeedRefresh()){
		this.executeMouseCursorChanges();
		CP.CustomMouseCursor.refreshBattlePhase();
	}
};

BattleManager.executeMouseCursorChanges = function(){
	var cursor = this.getPhaseCursor();
	if(!!cursor)
		CP.CustomMouseCursor.setMouseCursorType(cursor);
	else if(!!this._phase){
		if(CP.CustomMouseCursor.BATTLE_PHASE_TEST)
			console.log(this._phase);
		SceneManager.resetSceneMouseCursor();
	}
};

BattleManager.getPhaseCursor = function(){
	for(var i = 0; i < CP.CustomMouseCursor.BATTLE_CURSORS.length; i++){
		var cursor = CP.CustomMouseCursor.BATTLE_CURSORS[i];
		if(cursor.phase == BattleManager._phase)
			return cursor.cursorName;
	}

	return null;
};

//-----------------
// TouchInput
//-----------------
CP.CustomMouseCursor.INIT_TOUCH_INPUT = TouchInput.initialize;
TouchInput.initialize = function(){
	//说明
	//由于测试环境中，游戏启动后会自动触发一次mousemove事件但坐标是不准确的
	//因此第一次mousemove事件会被手动屏蔽
	//插件参数【是否自动触发移动事件】决定是否执行这个手动屏蔽
	this._hasMoved = !CP.CustomMouseCursor.AUTO_EXECUTE_MOVE_EVENT;
	CP.CustomMouseCursor.INIT_TOUCH_INPUT.call(this);
};

TouchInput.setMovedFlag = function(){
	this._hasMoved = true;
};

CP.CustomMouseCursor.ON_MOUSE_MOVE = TouchInput._onMouseMove;
TouchInput._onMouseMove = function(event){
    CP.CustomMouseCursor.ON_MOUSE_MOVE.call(this, event);
    if(this._hasMoved)
    	this.changeMousePosition(event);
    else
    	this.setMovedFlag();
};

CP.CustomMouseCursor.ON_MOUSE_DOWN = TouchInput._onMouseDown;
TouchInput._onMouseDown = function(event){
	CP.CustomMouseCursor.ON_MOUSE_DOWN.call(this, event);
	this.setMovedFlag();
	this.changeMousePosition(event);
};

TouchInput.changeMousePosition = function(event){
	var x = Graphics.pageToCanvasX(event.pageX);
    var y = Graphics.pageToCanvasY(event.pageY);

    CP.CustomMouseCursor.setMousePosition(x, y);
    CP.CustomMouseCursor.resetMouseWaitCount();
    SceneManager.showMouse();
};

//-----------------
// Graphics
//-----------------
CP.CustomMouseCursor.GRAPHICS_ON_WINDOW_RESIZE = Graphics._onWindowResize;
Graphics._onWindowResize = function(){
	CP.CustomMouseCursor.GRAPHICS_ON_WINDOW_RESIZE.call(this);
	SceneManager.resizeMouseRefresh();
};

//-----------------
// Scene_Base
//-----------------
Scene_Base.prototype.isMessageWindowPaused = function(){
	if(!CP.CustomMouseCursor.HAS_MESSAGE_PAUSE_CURSOR)
		return false;
	if(!this._messageWindow)
		return false;
	else if(!this._messageWindow.pause)
		return false;
	return this.isAnyMessageSubWindowActive();
};

Scene_Base.prototype.isAnyMessageSubWindowActive = function(){
	return true;
};

CP.CustomMouseCursor.SCENE_BASE_UPDATE = Scene_Base.prototype.update;
Scene_Base.prototype.update = function(){
	CP.CustomMouseCursor.SCENE_BASE_UPDATE.call(this);
	this.updateMessageSubWindowMouseCursor();
};

Scene_Base.prototype.updateMessageSubWindowMouseCursor = function(){
	if(this.isMessageWindowPaused())
		CP.CustomMouseCursor.setMouseCursorType(CP.CustomMouseCursor.MESSAGE_PAUSE_CURSOR);
};

//-----------------
// Scene_Boot
//-----------------
CP.CustomMouseCursor.BOOT_LOAD_SYSTEM_IMAGES = Scene_Boot.loadSystemImages;
Scene_Boot.loadSystemImages = function(){
	CP.CustomMouseCursor.BOOT_LOAD_SYSTEM_IMAGES.call(this);
	ImageManager.reserveAllMouse();
};

//-----------------
// Scene_Battle
//-----------------
CP.CustomMouseCursor.BATTLE_COMMAND_ATTACK = Scene_Battle.prototype.commandAttack;
Scene_Battle.prototype.commandAttack = function(){
	CP.CustomMouseCursor.BATTLE_COMMAND_ATTACK.call(this);
	CP.CustomMouseCursor.setMouseCursorType(CP.CustomMouseCursor.TARGET_CURSOR);
};

CP.CustomMouseCursor.ON_BATTLE_SKILL_OK = Scene_Battle.prototype.onSkillOk;
Scene_Battle.prototype.onSkillOk = function(){
    CP.CustomMouseCursor.ON_BATTLE_SKILL_OK.call(this);
    this.setActionOkCursor();
};

CP.CustomMouseCursor.ON_BATTLE_ITEM_OK = Scene_Battle.prototype.onItemOk;
Scene_Battle.prototype.onItemOk = function() {
    CP.CustomMouseCursor.ON_BATTLE_ITEM_OK.call(this);
    this.setActionOkCursor();
};

Scene_Battle.prototype.setActionOkCursor = function(){
	if(Imported.CP_PetCore && this._changePetWindow.isOpenAndActive())
		BattleManager.executeMouseCursorChanges();
	else
		CP.CustomMouseCursor.setMouseCursorType(CP.CustomMouseCursor.TARGET_CURSOR);
};

CP.CustomMouseCursor.ON_BATTLE_ACTOR_OK = Scene_Battle.prototype.onActorOk;
Scene_Battle.prototype.onActorOk = function(){
	CP.CustomMouseCursor.ON_BATTLE_ACTOR_OK.call(this);
	BattleManager.executeMouseCursorChanges();
};

CP.CustomMouseCursor.ON_BATTLE_ACTOR_CANCEL = Scene_Battle.prototype.onActorCancel;
Scene_Battle.prototype.onActorCancel = function(){
	CP.CustomMouseCursor.ON_BATTLE_ACTOR_CANCEL.call(this);
	BattleManager.executeMouseCursorChanges();
};

CP.CustomMouseCursor.ON_BATTLE_ENEMY_OK = Scene_Battle.prototype.onEnemyOk;
Scene_Battle.prototype.onEnemyOk = function(){
	CP.CustomMouseCursor.ON_BATTLE_ENEMY_OK.call(this);
	BattleManager.executeMouseCursorChanges();
};

CP.CustomMouseCursor.ON_BATTLE_ENEMY_CANCEL = Scene_Battle.prototype.onEnemyCancel;
Scene_Battle.prototype.onEnemyCancel = function(){
	CP.CustomMouseCursor.ON_BATTLE_ENEMY_CANCEL.call(this);
	BattleManager.executeMouseCursorChanges();
};

//-----------------
// 主程序
//-----------------
if(!Utils.isMobileDevice())
	CP.CustomMouseCursor.hideMouse();
CP.CustomMouseCursor.setMouseCursorType(CP.CustomMouseCursor.DEFAULT_CURSOR);